/**
 * MongoDB
 * Created on 2016/06/29
 */
var express = require('express');
var router = express.Router();
var CONFIG = require('../../common/config');
var CODE = require('../../common/code');
var rpcFunc=require('../routes/rpcSrv/rpcFunc.js');
var async  = require( 'async'); // 同步控制

var ItbTemplateModel = require('../../common/mysql/mapping/ItbTemplateModel');
var ItbTmplPageModel = require('../../common/mysql/mapping/ItbTmplPageModel');
var ItbDocumentModel = require('../../common/mysql/mapping/ItbDocumentModel');
var ItbPageModel = require('../../common/mysql/mapping/ItbPageModel');
var ItbDocTypeRModel = require('../../common/mysql/mapping/ItbDocTypeRModel');

var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;

var server = new mongodb.Server(CONFIG.MGDB_DOMAIN, CONFIG.MGDB_PORT, {auto_reconnect:true});
var db = new mongodb.Db(CONFIG.MGDB_DBNAME, server, {safe:true});

// MongoDB Collections
var DB_COL={
    COL_REL_TMPL_INFO:  'relTmplInfo',// 关联模版信息
    COL_PAGE_INFO:      'pageInfo',// 模版页信息
}

// replace对象标记位
var REP_TAG={
    TAG_NONE:       0,
    TAG_TITLE:      1,
    TAG_SUB_TITLE:  2,
    TAG_COMMENT:    4,
    TAG_TEXT:       8,
    TAG_IMAGE:      16,
    TAG_IMG_TXT:    32,
    TAG_CHART:      64,
    TAG_TABLE:      128,
}
// 编组类型
var REP_GRP={
    REP_TITLEGROUP:         1,
    REP_TEXTGROUP:          2, //[废弃]
    REP_IMAGEGROUP:         3,
    REP_CHARTGROUP:         4,
    REP_TABLEGROUP:         5,
    REP_IMAGETEXTGROUP:     6, //[废弃]
    REP_TEXTGROUP2:         7,
    REP_IMAGETEXTGROUP2:    8,
    REP_COMMENTGROUP:       9,
}

//--------------------------------------------------
/* Test. */
router.get('/', function(req, res, next) {
    db.open(function(err, db){
        if(!err){
            console.log('Connect MongoDB');

            db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(err, ret){
                var collection = db.collection(DB_COL.COL_PAGE_INFO);
                collection.count(function(err, count){
                    console.log('PageInfo Cnt: '+count);

                    db.close();
                    console.log('Close MongoDB');
                });
            });
        }else{
            console.log(err);
        }
    });

    res.send('Respond from Mongo');
});
//--------------------------------------------------


//--------------------------------------------------
/**
 * 从[二维数组]的每个[子数组]中找出一项，值各不相同
 * @param arrData 二维(数值)数组: [[0],[1,2],[0,3],[2] ...]
 * @index 当前[子数组]下标
 * @loopRet 返回数组: [0,1,3,2 ...]
 * return: TRUE/FALSE
 */
function loopArr(arrData, index, loopRet){

    if(index < arrData.length && loopRet){
        var subArr=arrData[index];
        for(var i in subArr){
            if(index==0){
                loopRet.splice(0,loopRet.length);
                //console.log("Redo");
            }

            var item=subArr[i];
            var ok=true;
            for(var n in loopRet){
                if(item == loopRet[n]){
                    ok=false;
                    break;
                }
            }
            if(ok){
                var curLen=loopRet.length;
                loopRet.push(item);
                //console.log(loopRet);
                if(loopRet.length==arrData.length){
                    return true;
                }
                if(index+1<arrData.length){
                    if(loopArr(arrData, index+1, loopRet)){
                        return true;
                    }else{
                        loopRet.splice(curLen,loopRet.length-curLen);
                        //console.log(loopRet+" recheck");
                    }
                }
            }
        }
    }

    return false;
}
//--------------------------------------------------

//--------------------------------------------------
/**
 * 获取匹配的replace对应关系
 * bStrict: 是否精确比较
 * return: [0,3,1,2...]
 *         数组下标对应replaces下标
 *         数组元素值代表cmpReplaces下标
 */
function getReplacesRel(replaces,cmpReplaces,bStrict){

    // 用于缓存匹配的replace对应关系
    // 二维数组: [[0],[1,2],[3] ...]
    var repRel=[];
    var bSkip=false;

    for(var i in replaces){// 本模版page的replaces
        var item=new Array();// 所有匹配的被比较replace下标
        var rep=replaces[i];

        for(var n in cmpReplaces){// 被比较模版page的replaces
            var cmpRep=cmpReplaces[n];
            var bOK=false;

            if( rep.kind==cmpRep.kind
                && rep.min>=cmpRep.min && rep.max<=cmpRep.max ) {

                // 非精确比较
                bOK=true;

                if(bStrict) {// 精确比较
                    // 标题组
                    if(REP_GRP.REP_TITLEGROUP==rep.kind) {
                        if(rep.value.length<=cmpRep.value.length) {
                            // 主标题始终在第一个,且移动端不能删除主标题
                            for(var t in rep.value) {
                                if(rep.value[t].min<cmpRep.value[t].min
                                    || rep.value[t].max>cmpRep.value[t].max) {
                                    console.log("REP_TITLEGROUP min/max NG");
                                    bOK=false;
                                    break;
                                }
                            }
                        } else {
                            console.log("REP_TITLEGROUP len NG");
                            bOK=false;
                        }

                        // 备注组
                    } else if(REP_GRP.REP_COMMENTGROUP==rep.kind) {
                        if(rep.value.length==cmpRep.value.length) {
                            for(var t in rep.value){
                                if(rep.value[t].min<cmpRep.value[t].min
                                    || rep.value[t].max>cmpRep.value[t].max) {
                                    console.log("REP_COMMENTGROUP min/max NG");
                                    bOK=false;
                                    break;
                                }
                            }
                        } else {
                            console.log("REP_COMMENTGROUP len NG");
                            bOK=false;
                        }

                        // 文字组
                    } else if(REP_GRP.REP_TEXTGROUP2==rep.kind) {
                        if(rep.value.length>=rep.min && cmpRep.value.length>cmpRep.min
                            && rep.value[0] && cmpRep.value[0]) {
                            // 只比较第一个subgroup
                            if(rep.value[0].type == cmpRep.value[0].type){// SJGSubGroupText
                                if(rep.value[0].value.length == cmpRep.value[0].value.length) {// 正文/小标题
                                    for(var t in rep.value[0].value){
                                        if((rep.value[0].value[t].tt != cmpRep.value[0].value[t].tt)
                                            || (rep.value[0].value[t].min < cmpRep.value[0].value[t].min)
                                            || (rep.value[0].value[t].max > cmpRep.value[0].value[t].max)){

                                            console.log("REP_TEXTGROUP2 tt/min/max NG");
                                            bOK=false;
                                            break;
                                        }
                                    }
                                } else {
                                    console.log("REP_TEXTGROUP2 subGrp-item len NG");
                                    bOK=false;
                                }
                            } else {
                                console.log("REP_TEXTGROUP2 subGrp type NG");
                                bOK=false;
                            }
                        } else {
                            console.log("REP_TEXTGROUP2 len NG");
                            bOK=false;
                        }

                        // 图片组
                    } else if(REP_GRP.REP_IMAGEGROUP==rep.kind) {
                        // TODO

                        // 图文组
                    } else if(REP_GRP.REP_IMAGETEXTGROUP2==rep.kind) {
                        if(rep.value.length>=rep.min && cmpRep.value.length>cmpRep.min
                            && rep.value[0] && cmpRep.value[0]) {
                            // 只比较第一个subgroup
                            if(rep.value[0].type == cmpRep.value[0].type){// SJGSubGroupImageText
                                if(rep.value[0].image && cmpRep.value[0].image) {// 图像
                                    // TODO
                                }
                                if(rep.value[0].textArr.value.length == cmpRep.value[0].textArr.value.length) {// 文字
                                    for(var t in rep.value[0].textArr.value){
                                        if(rep.value[0].textArr.value[t].tt != cmpRep.value[0].textArr.value[t].tt
                                            || rep.value[0].textArr.value[t].min < cmpRep.value[0].textArr.value[t].min
                                            || rep.value[0].textArr.value[t].max > cmpRep.value[0].textArr.value[t].max) {

                                            console.log("REP_IMAGETEXTGROUP2 tt/min/max NG");
                                            bOK=false;
                                            break;
                                        }
                                    }
                                } else {
                                    console.log("REP_IMAGETEXTGROUP2 subGrp-item len NG");
                                    bOK=false;
                                }
                            } else {
                                console.log("REP_IMAGETEXTGROUP2 subGrp type NG");
                                bOK=false;
                            }

                        } else {
                            console.log("REP_IMAGETEXTGROUP2 len NG");
                            bOK=false;
                        }

                        // 图表组
                    } else if(REP_GRP.REP_CHARTGROUP==rep.kind) {
                        if(rep.value.length>=rep.min && cmpRep.value.length>=cmpRep.min
                            && rep.value[0] && cmpRep.value[0]) {
                            // 只比较第一个item
                            if(rep.value[0].type != cmpRep.value[0].type) {// 类型需一致
                                console.log("REP_CHARTGROUP type NG");
                                bOK=false;
                            }

                        } else {
                            console.log("REP_CHARTGROUP len NG");
                            bOK=false;
                        }

                        // 表格组
                    } else if(REP_GRP.REP_TABLEGROUP==rep.kind) {
                        // TODO
                    }
                }
            }

            if(bOK) {
                // OK 记录匹配的被比较replace下标
                item.push(n);
            }
        }

        if(item.length==0){
            // 只要有一个replace不匹配则退出
            bSkip=true;
            repRel.splice(0,repRel.length);
            break;
        }else{
            repRel.push(item);
        }
    }

    if(!bSkip){
        // 获取相互不重复的replace对应关系
        var ret=[];
        if(loopArr(repRel,0, ret)){
            return ret;
        }
    }

    return null;
}
//--------------------------------------------------

//--------------------------------------------------
/**
 * 比较两模版是否可以匹配
 * @param pagesInfo: 当前模版的pages信息: [...]
 * @param cmpTmplData: 被比较模版信息: {tmpl_id:111, pages:[...]}
 * @param callback
 * 返回值格式:
 {
     "cmp_tmpl_id":4017,
     "rel_pages":[
         {
             "page_index": 0,
             "page_id":214855,
             "cmp_page_id":214425
         },
         {
             "page_index": 0,
             "page_id":214791,
             "rel_page_id":214435
         }
     ]
 }
 */
function chkRelTmpl(pagesInfo, cmpTmplData, callback){
    // 循环本模版的pages
    var subAsyncFuncs = [];
    for(var n in pagesInfo) {
        subAsyncFuncs.push((function(idx, pageData){
            return function(subCallback){
                var subRetInfo = {
                    page_index: pageData.page_index,// 当前模版page下标
                    cmp_pages_index: []// 被比较模版中所有能匹配的page下标
                };

                var reps=JSON.parse((pageData.replaces||'[]').replace(/\n/g,'\\n'));// 当前模版页replaces
                // 循环被比较模版的pages
                for(var m in cmpTmplData.pages) {
                    var cmpPageData=cmpTmplData.pages[m];
                    console.log("PageId:"+cmpPageData.page_id);
                    var cmpReps=JSON.parse((cmpPageData.replaces||'[]').replace(/\n/g,'\\n'));// 被比较模版页replaces

                    // 被比较模版页的replace种类包含当前模版页的replace种类 TODO
                    var chkTag=pageData.rep_hash_tag & cmpPageData.rep_hash_tag;
                    if((chkTag != pageData.rep_hash_tag)
                        || (reps && cmpReps && reps.length > cmpReps.length)) {
                        continue;
                    }

                    // 被比较模版页的replace种类和当前模版页的replace种类相同 TODO
                    //if((pageData.rep_hash_tag != cmpPageData.rep_hash_tag)
                    //    || (reps && cmpReps && reps.length > cmpReps.length)){
                    //    continue;
                    //}

                    // 比较2个page的replaces是否匹配
                    var repRel = getReplacesRel(reps, cmpReps, true);// 严格匹配
                    if (repRel){
                        // 如果符合条件,则记录该被比较的page下标
                        subRetInfo.cmp_pages_index.push(cmpPageData.page_index);
                    }
                }

                return subCallback(null, subRetInfo);
            }
        })(n, pagesInfo[n]));
    }
    // 并行执行
    async.parallel(subAsyncFuncs, function(subErr, subResults){
        if(subErr){
            console.log('mongo.js [chkRelTmpl] async Err: '+subErr);
            return callback(subErr, null);
        }

        // 按当前模版page_index正序排序
        var subRet = subResults.sort(function(a,b){
            return a.page_index - b.page_index;
        });

        // 转成用于比较的二维数组
        var pageRelArr=[];
        for(var s in subRet){
            // 只要有一页未匹配,则整个被比较模版不匹配
            if(subRet[s].cmp_pages_index.length==0){
                pageRelArr=[];
                break;
            }
            pageRelArr.push(subRet[s].cmp_pages_index);
        }

        // 回调用返回值
        var callbackRet={
            cmp_tmpl_id: cmpTmplData.tmpl_id,
            rel_pages:[]
        };
        if(pageRelArr.length==pagesInfo.length){
            // 获取相互不重复的page对应关系
            var retPageRel=[];
            if(loopArr(pageRelArr,0, retPageRel)){
                console.log('mongo.js [chkRelTmpl] cmp_tmpl:'+cmpTmplData.tmpl_id+' OK! '+ retPageRel);
                // 被比较模版可以匹配
                for(var i in retPageRel){
                    callbackRet.rel_pages.push({
                        page_index: i,
                        page_id: pagesInfo[i].page_id,
                        cmp_page_id: cmpTmplData.pages[retPageRel[i]].page_id
                    });
                }
            }else{
                console.log('mongo.js [chkRelTmpl] cmp_tmpl:'+cmpTmplData.tmpl_id+' Part-NG!');
            }
        }else{
            //存在未匹配的page,需跳过被比较模版
            console.log('mongo.js [chkRelTmpl] cmp_tmpl:'+cmpTmplData.tmpl_id+' NG!');
        }

        return callback(null, callbackRet);

    });
}
//--------------------------------------------------

//--------------------------------------------------
/**
 * 刷新当前模版的关联模版信息到MongoDB
 * 参数 device: 0表示从pc来的请求
 *             1表示ios
 *             2表示android
 *             101表示pc美化大师
 *             102表示pc wps
 *             103表示wps android
 *             104表示wps ios
 * 参数 tmplId: 当前模版id
 *
 * 数据结构:
    {
        "_id":"578e742af49724fbdf56db46",
        "tmpl_id":4017,
        "type":[
            {
                "category":1,
                "type_index":0
            }
        ],
        "rel_tmpl_info":[
            {
                "rel_tmpl_id":4012,
                "rel_pages":[
                    [
                        {
                            "page_id":214855,
                            "rel_page_id":214425
                        },
                        {
                            "page_id":214791,
                            "rel_page_id":214435
                        },
                        {
                            "page_id":214811,
                            "rel_page_id":214455
                        },
                        {
                            "page_id":214812,
                            "rel_page_id":214458
                        },
                        {
                            "page_id":214815,
                            "rel_page_id":214436
                        }
                    ]
                ]
            }
        ],
        "create_time": "2016-07-20T02:38:19.954Z"
    }
 */
function refreshRelInfo(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");// 设置跨域访问

    var device = req.body.device || req.query.device;
    var tmplId = Number(req.body.tmplId || req.query.tmplId);

    // return function
    function ret_func(success, msg, data){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    }

    if (typeof tmplId=='undefined' || tmplId==null || tmplId==0) {
        return ret_func(0,"模版id为空");
    }

    // proc
    async.parallel({
        getPagesInfo: function(callback){
            // 取当前模版页数据
            var ent = new ItbTmplPageModel({
                tmpl_ids : tmplId
            });
            ent.getPagesInfoByTmplIds(function(err, pageInfo) {
                if (err) {
                    console.log('mongo.js [refreshRelInfo] get PageInfo Err: ' + err);
                    return callback(err, null);
                } else {
                    if (pageInfo && pageInfo.length > 0) {
                        // 将当前模版页信息更新到MongoDB
                        db.open(function(err2, db){
                            if (err2) {
                                console.log('mongo.js [refreshRelInfo] openDB Err: '+err2);
                                return callback(err2, null);
                            }
                            // DB认证
                            db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(authErr, authRet){
                                if (authErr) {
                                    console.log('mongo.js [refreshRelInfo] DB-Auth Err: '+authErr);
                                    return callback(authErr, null);
                                }

                                console.log('Open MongoDB');
                                var collection = db.collection(DB_COL.COL_PAGE_INFO);
                                // 删除旧的页信息
                                // *检索条件注意区分数字与字符串
                                collection.deleteMany({"tmpl_id": tmplId},function(err3, delRet){
                                    if (err3) {
                                        console.log('mongo.js [refreshRelInfo] del MgDB-PageInfo Err: '+err3);
                                        return callback(err3, null);
                                    }

                                    var insData=[];
                                    /* Generate Timestamp and convert for mongodb */
                                    //var ts = new Date().getTime();
                                    //var i = ts % 1000;
                                    //var t = new mongodb.BSONPure.Timestamp(i, Math.floor(ts * 0.001));
                                    for(var i in pageInfo){
                                        var info=pageInfo[i];
                                        insData.push({
                                            tmpl_id: info.tmpl_id,
                                            page_id: info.page_id,
                                            page_index: info.page_index,
                                            base_page_id: info.base_page_id,
                                            rep_hash_tag: info.rep_hash_tag,
                                            replaces: info.replaces||'[]',
                                            create_time: new Date().toISOString(),
                                        });
                                    }
                                    // 插入新的页信息
                                    collection.insertMany(insData, function(err4, insRet){
                                        if (err4) {
                                            console.log('mongo.js [refreshRelInfo] ins MgDB-PageInfo Err: '+err4);
                                            return callback(err4, null);
                                        }

                                        db.close();
                                        console.log('Close MongoDB');
                                        return callback(null, pageInfo);
                                    });
                                });
                            });
                        });
                    } else {
                        console.log('mongo.js [refreshRelInfo] No PageInfo');
                        callback("模版页数据不存在", null);
                    }
                }
            });
        },

        getTypeInfo: function(callback){
            // 取当前模版分类信息
            var ent2 = new ItbDocTypeRModel({
                doc_id: tmplId
            });
            ent2.getTypeInfoByDocId(function(err2, typeInfo){
                if (err2) {
                    console.log('mongo.js [refreshRelInfo] getTypeInfo Err: ' + err2);
                    callback(err2, null);
                } else {
                    if (typeInfo && typeInfo.length > 0) {
                        var retInfo=[];
                        for(var i in typeInfo) {
                            retInfo.push({category:typeInfo[i].category, type_index:typeInfo[i].type_index});
                        }
                        callback(null, retInfo);

                    } else {
                        console.log('mongo.js [refreshRelInfo] No TypeInfo');
                        callback(null, []);
                    }
                }
            });
        }

    }, function(error, result){
        if (error) {
            return ret_func(0,CODE.OPERATION_FAILED);
        }

        var pagesInfo = result.getPagesInfo;// 本模版pages
        var typeInfo = result.getTypeInfo;

        // 获取全部模版
        var entity = new ItbTmplPageModel({
        });
        entity.getAllTmplPagesInfoForSwitch(function(err, allTmplPagesInfo) {
            if (err) {
                console.log('mongo.js [refreshRelInfo] get allTmplPagesInfo Err: ' + err);
                return ret_func(0,CODE.OPERATION_FAILED);
            }

            // 返回结果是以模版为单位
            if (allTmplPagesInfo && allTmplPagesInfo.length > 0) {

                // 循环所有被比较模版
                var asyncFuncs = [];
                for(var i in allTmplPagesInfo) {
                    if(allTmplPagesInfo[i].tmpl_id == tmplId) {
                        continue;// 跳过自己
                    }
                    asyncFuncs.push((function(index, tmplData){
                        return function(callback){
                            chkRelTmpl(pagesInfo, tmplData, function(chkErr, chkRet){
                                callback(chkErr, chkRet);
                            });
                        }
                    })(i, allTmplPagesInfo[i]));
                }
                // 并行执行
                async.parallelLimit(asyncFuncs, 20, function (err, results) {
                    if (err) {
                        console.log('mongo.js [refreshRelInfo] async-AllTmpl Err: '+err);
                        return ret_func(0,CODE.OPERATION_FAILED);
                    }

                    // 构建插入DB用数据结构
                    var db_data = {
                        tmpl_id: tmplId,
                        type: typeInfo,
                        rel_tmpl_info: []
                    };

                    // 整理返回值
                    for(var r in results){// 循环被比较模版
                        var relTmplItem={
                            rel_tmpl_id: results[r].cmp_tmpl_id,
                            rel_pages:[]
                        }

                        // 匹配的场合
                        if(results[r].rel_pages.length>0){
                            // 循环模版页匹配信息
                            var relPagesItem=[];
                            for(var s in results[r].rel_pages){
                                relPagesItem.push({
                                    page_id: results[r].rel_pages[s].page_id,
                                    rel_page_id: results[r].rel_pages[s].cmp_page_id
                                });
                            }
                            // 目前只有一组匹配的页对应关系,以后可扩展多组 TODO
                            relTmplItem.rel_pages.push(relPagesItem);

                            db_data.rel_tmpl_info.push(relTmplItem);
                        }
                    }

                    // 存入mongoDB
                    if(db_data.rel_tmpl_info.length>0
                        && db_data.rel_tmpl_info[0].rel_pages.length>0
                        && db_data.rel_tmpl_info[0].rel_pages[0].length==pagesInfo.length) {

                        db.open(function(err2, db){
                            if (err2) {
                                console.log('mongo.js [refreshRelInfo] openDB Err: '+err2);
                                return ret_func(0,CODE.OPERATION_FAILED);
                            }
                            // DB认证
                            db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(authErr, authRet){
                                if (authErr) {
                                    console.log('mongo.js [refreshRelInfo] DB-Auth Err: '+authErr);
                                    return ret_func(0,CODE.OPERATION_FAILED);
                                }

                                console.log('Open MongoDB');
                                db_data.create_time=new Date().toISOString();// 创建时间

                                var collection = db.collection(DB_COL.COL_REL_TMPL_INFO);
                                collection.findOneAndUpdate({"tmpl_id": tmplId}
                                    ,{$set:db_data}
                                    ,{
                                        returnOriginal: false,
                                        upsert: true// 有则更新,无则插入
                                    }
                                    ,function(err3, ret){
                                        if (err3) {
                                            console.log('mongo.js [refreshRelInfo] findOneAndUpdate Err: '+err3);
                                            return ret_func(0,CODE.OPERATION_FAILED);
                                        }

                                        console.log("FindOneAndUpdate:"+JSON.stringify(ret.value));
                                        db.close();
                                        console.log('Close MongoDB');

                                        // 更新其它与当前模版关联的模版
                                        updOtherRelInfo(tmplId, false, function(updErr, updRet){
                                            return ret_func(1,CODE.OPERATION_SUCCESS);
                                        });
                                    }
                                );
                            });
                        });
                    } else {
                        return ret_func(0,'模版均不匹配');
                    }
                });

            } else {
                return ret_func(0,'未找到模版');
            }
        });
    });
}
router.get('/refreshRelInfo', refreshRelInfo);
router.post('/refreshRelInfo', refreshRelInfo);
//--------------------------------------------------

//--------------------------------------------------
/**
 * 更新与当前模版关联的模版信息
 * 参数 tmplId: 当前模版id
 * 参数 cancelFlg: 当前模版是否取消发布
 */
function updOtherRelInfo(tmplId, cancelFlg, callback) {
    db.open(function(err, db){
        if (err) {
            console.log('mongo.js [updOtherRelInfo] openDB Err: '+err);
            return callback(err, null);
        }
        // DB认证
        db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(authErr, authRet){
            if (authErr) {
                console.log('mongo.js [updOtherRelInfo] DB-Auth Err: '+authErr);
                return callback(authErr, null);
            }

            console.log('Open MongoDB');
            var colRel = db.collection(DB_COL.COL_REL_TMPL_INFO);
            var colPage = db.collection(DB_COL.COL_PAGE_INFO);

            // 取消的场合
            if(cancelFlg){
                // 可直接批量更新
                colRel.updateMany(
                    {"rel_tmpl_info.rel_tmpl_id": tmplId},
                    {$pull:{"rel_tmpl_info":{"rel_tmpl_id":tmplId}}},// 从关联模版中删除当前模版信息
                    function(updErr,updRet){
                        if (updErr) {
                            console.log('mongo.js [updOtherRelInfo] updMany Rel-Tmpls Err: '+updErr);
                            return callback(updErr, null);
                        }

                        db.close();db.serverStatus
                        console.log('Close MongoDB');
                        return callback(null,null);
                    });

            // 发布的场合
            } else {
                // 检索所有关联模版
                colRel.find({
                    "rel_tmpl_info":{$elemMatch:{"rel_tmpl_id":tmplId}}
                }).toArray(function(findErr, relTmplsRet){
                    if (findErr) {
                        console.log('mongo.js [updOtherRelInfo] find RelTmpls Err: '+findErr);
                        return callback(findErr, null);
                    }

                    if(relTmplsRet && relTmplsRet.length>0){
                        // 检索当前模版pages信息
                        colPage.find({"tmpl_id":tmplId}).toArray(function(findErr2, pagesInfo){
                            if (findErr2) {
                                console.log('mongo.js [updOtherRelInfo] find This-PageInfo Err: '+findErr2);
                                return callback(findErr2, null);
                            }

                            // 循环所有关联模版
                            var asyncFuncs = [];
                            for(var i in relTmplsRet) {
                                asyncFuncs.push((function(index, relTmplInfo){
                                    return function(subCallback){
                                        // 获取关联模版pages信息
                                        colPage.find({"tmpl_id":relTmplInfo.tmpl_id}).toArray(function(err, relTmplPagesInfo) {
                                            if (err) {
                                                console.log('mongo.js [updOtherRelInfo] find Other-PageInfo Err: ' + err);
                                                return subCallback(err, null);
                                            }

                                            relTmplPagesInfo = relTmplPagesInfo||[];
                                            var cmpPagesInfo={
                                                tmpl_id:tmplId,
                                                pages:pagesInfo
                                            }
                                            chkRelTmpl(relTmplPagesInfo, cmpPagesInfo, function(chkErr, chkRet){

                                                if(chkRet.rel_pages.length>0){
                                                    // 匹配时 更新
                                                    var updItem={
                                                        rel_tmpl_id:chkRet.cmp_tmpl_id,
                                                        rel_pages:[]
                                                    };
                                                    var relPagesItem=[];
                                                    for(var r in chkRet.rel_pages){
                                                        relPagesItem.push({
                                                            page_id: chkRet.rel_pages[r].page_id,
                                                            rel_page_id: chkRet.rel_pages[r].cmp_page_id
                                                        });
                                                    }
                                                    // 目前只有一组匹配的页对应关系,以后可扩展多组 TODO
                                                    updItem.rel_pages.push(relPagesItem);

                                                    // 更新对应的rel_pages
                                                    colRel.updateOne(
                                                        {"tmpl_id":chkRet.cmp_tmpl_id, "rel_tmpl_info.rel_tmpl_id":tmplId},
                                                        {$set:{"rel_tmpl_info.$.rel_pages":updItem.rel_pages}},
                                                        function(updErr,updRet){
                                                            if (updErr) {
                                                                console.log('mongo.js [updOtherRelInfo] updOne Rel-Tmpl Err: '+updErr);
                                                                return callback(updErr, null);
                                                            }
                                                            return callback(null,null);
                                                        });

                                                }else{
                                                    // 不匹配时 删除
                                                    colRel.updateOne(
                                                        {"tmpl_id":relTmplInfo.tmpl_id},
                                                        {$pull:{"rel_tmpl_info":{"rel_tmpl_id":tmplId}}},// 从关联模版中删除当前模版信息
                                                        function(updErr,updRet){
                                                            if (updErr) {
                                                                console.log('mongo.js [updOtherRelInfo] updOne Rel-Tmpl Err: '+updErr);
                                                                return callback(updErr, null);
                                                            }
                                                            return callback(null,null);
                                                        });
                                                }
                                            });
                                        });
                                    }
                                })(i, relTmplsRet[i]));
                            }
                            // 并行执行
                            async.parallel(asyncFuncs, function (err, results) {
                                if (err) {
                                    console.log('mongo.js [refreshRelInfo] async-AllTmpl Err: ' + err);
                                    return ret_func(0, CODE.OPERATION_FAILED);
                                }

                                db.close();
                                console.log('Close MongoDB');
                                return callback(null,null);
                            });
                        });

                    }else{
                        db.close();
                        console.log('Close MongoDB');
                        return callback(null,null);
                    }
                });
            }
        });
    });
}
//--------------------------------------------------

//--------------------------------------------------
/**
 * 切换模版
 * 参数 device: 0表示从pc来的请求
 *             1表示ios
 *             2表示android
 *             101表示pc美化大师
 *             102表示pc wps
 *             103表示wps android
 *             104表示wps ios
 * 参数 docId: 用户文档id
 * 参数 tmplId: 原始模版id
 * 参数 usedIds: 切换过的模版id(数组[])
 */
function chgTmpl(req, res, next) {
    var device = req.body.device || req.query.device;
    var docId = req.body.docId || req.query.docId;
    var tmplId = Number(req.body.tmplId || req.query.tmplId);
    var usedIds = req.body.usedIds || req.query.usedIds || [];

    // return function
    function ret_func(success, msg, data){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    }

    if (typeof docId=='undefined' || docId==null) {
        return ret_func(0,"用户文档id为空");
    }
    if (typeof tmplId=='undefined' || tmplId==null || tmplId==0) {
        return ret_func(0,"模版id为空");
    }

    // proc
    async.parallel({
        getRelTmplInfo: function(callback){
            // 查找关联模版信息
            db.open(function(err, db){
                if(err){
                    console.log('mongo.js [chgTmpl] open MongoDB Err:'+err);
                    return callback(err,null);
                }
                // DB认证
                db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(authErr, authRet){
                    if (authErr) {
                        console.log('mongo.js [chgTmpl] DB-Auth Err: '+authErr);
                        return callback(authErr, null);
                    }

                    console.log('Open MongoDB');
                    var collection = db.collection(DB_COL.COL_REL_TMPL_INFO);
                    collection.find({'tmpl_id':tmplId}).toArray(function(err2,rets){
                        if(err2){
                            console.log('mongo.js [chgTmpl] find collection Err:'+err2);
                            return callback(err2,null);
                        }

                        var cbRet = null;
                        if(rets && rets.length>0){
                            cbRet=rets[0];
                        }

                        db.close();
                        console.log('Close MongoDB');
                        return callback(null,cbRet);
                    });
                });
            });
        },

        getUserPagesInfo: function(callback){
            // 取用户文档页数据
            var ent = new ItbDocumentModel({
                doc_id: docId
            });
            ent.getPagesInfoByDocId(function(err, docPagesInfo){
                if (err) {
                    console.log('mongo.js [chgTmpl] getUserDocInfo Err:' + err);
                    return callback(err, null);
                }

                return callback(null, docPagesInfo);
            });
        }

    }, function(error, result) {
        if (error) {
            return ret_func(0, CODE.OPERATION_FAILED);
        }

        // 获取关联模版信息
        var relTmplsInfo = result.getRelTmplInfo;
        // 获取用户文档页信息
        var userPagesInfo = result.getUserPagesInfo;

        if(relTmplsInfo && relTmplsInfo.rel_tmpl_info && relTmplsInfo.rel_tmpl_info.length>0){
            var chgOK=false;

            var asyncFuncs = [];
            for(var n in relTmplsInfo.rel_tmpl_info) {// 循环可能匹配的模版
                // 跳过已使用过的模版
                var skipFlg = false;
                for(var u in usedIds){
                    if(relTmplsInfo.rel_tmpl_info[n].rel_tmpl_id == usedIds[u]) {
                        skipFlg = true;
                        break;
                    }
                }
                if(skipFlg){
                    continue;
                }

                asyncFuncs.push((function (index, relTmplInfo) {
                    return function (asyncCallback) {
                        // 尝试切换模版
                        chgTmplProc(relTmplInfo, userPagesInfo, function(err, ret){
                            if(err) {
                                // 切换失败则继续尝试下一个模版
                                return asyncCallback(null, relTmplInfo.rel_tmpl_id);
                            }
                            // 切换成功则中断退出
                            return asyncCallback('OK', relTmplInfo.rel_tmpl_id);
                        });
                    }

                })(n, relTmplsInfo.rel_tmpl_info[n])); // 利用闭包解决动态参数传递问题
            }
            // 按模版串行依次执行, 如果切换成功则利用err来中断
            async.series(asyncFuncs, function (err, ret) {
                if (err=='OK') {
                    return ret_func(1,CODE.OPERATION_SUCCESS,ret);
                } else {
                    return ret_func(0, '模版均不匹配');
                }
            });

        } else {
            return ret_func(0, '未找到匹配模版');
        }
    });

}
router.get('/chgTmpl', chgTmpl);
router.post('/chgTmpl', chgTmpl);
//--------------------------------------------------

//--------------------------------------------------
/**
 * 尝试切换模版
 * @param relTmplInfo: 原模版与目标模版的page对应信息
 * {
 *      rel_tmpl_id: 100,
 *      rel_pages: [
 *          {
 *              page_id: 91,
 *              rel_page_id: 101,
 *              rel_replaces: ''
 *          },
 *          ...
 *      ]
 * }
 * @param userPages: 用户文档页信息
 */
function chgTmplProc(relTmplInfo, userPages, callback) {

    // 从MongoDB获取目标模版页信息
    db.open(function(err, db){
        if(err){
            console.log('mongo.js [chgTmplProc] open MongoDB Err:'+err);
            return callback('NG',null);
        }
        // DB认证
        db.authenticate(CONFIG.MGDB_USER,CONFIG.MGDB_PASSWORD,function(authErr, authRet){
            if (authErr) {
                console.log('mongo.js [chgTmplProc] DB-Auth Err: '+authErr);
                return callback(authErr, null);
            }

            console.log('Open MongoDB');
            var collection = db.collection(DB_COL.COL_PAGE_INFO);
            collection.find({'tmpl_id':relTmplInfo.rel_tmpl_id}).toArray(function(err2,rets){
                if(err2){
                    console.log('mongo.js [chgTmplProc] find COL_PAGE_INFO Err:'+err2);
                    return callback('NG',null);
                }

                db.close();
                console.log('Close MongoDB');

                if(rets && rets.length>0){
                    // 取得目标模版页的replaces信息
                    for(var n in relTmplInfo.rel_pages[0]){
                        for(var i in rets){
                            if(rets[i].page_id==relTmplInfo.rel_pages[0][n].rel_page_id) {
                                relTmplInfo.rel_pages[0][n].rel_replaces=rets[i].replaces;
                                break;
                            }
                        }
                    }

                    // 更新用数据:{page_id:用户文档页id, base_page_id:目标模版页id, replaces:更新的rep信息}
                    var updData=[];

                    // 检查用户文档的replaces是否能切换到目标模版页
                    for(var i in userPages) {
                        var userPage=userPages[i];
                        var userReplaces=JSON.parse((userPage.replaces||'[]').replace(/\n/g,'\\n'));

                        for(var n in relTmplInfo.rel_pages[0]) {
                            var relPage=relTmplInfo.rel_pages[0][n];
                            if(relPage.page_id == userPage.base_page_id) {
                                var relPageReplaces=JSON.parse((relPage.rel_replaces || '[]').replace(/\n/g,'\\n'));

                                // 比较2个page的replaces是否匹配
                                var repsRel = getReplacesRel(userReplaces, relPageReplaces, true);
                                if (repsRel){
                                    var newReplaces=[];
                                    for(var r in repsRel){
                                        var newRep=userReplaces[r];
                                        newRep.id=relPageReplaces[repsRel[r]].id;
                                        newReplaces.push(newRep);
                                    }

                                    // 可以匹配，更新用户文档replaces的对象id
                                    updData.push({
                                        page_id: userPage.page_id,
                                        base_page_id: relPage.rel_page_id,
                                        replaces: JSON.stringify(newReplaces)
                                    });

                                } else{
                                    console.log('mongo.js [chgTmplProc] page-replaces NG');
                                    return callback("NG", null);
                                }
                                break;
                            }
                        }
                    }

                    if(updData.length==userPages.length){
                        // 更新用户文档
                        var updEnt=new ItbDocumentModel({
                            doc_id: userPages[0].doc_id,
                            base_doc_id: relTmplInfo.rel_tmpl_id,// 目标模版id
                        });
                        updEnt.updateToDB(function(err3, updDocRet){
                            if(err3) {
                                console.log('mongo.js [chgTmplProc] upd User-Doc err:'+err3);
                                return callback("NG", null);
                            }
                            console.log('mongo.js [chgTmplProc] upd User-Doc OK');

                            // 更新用户文档页
                            var updEnt2=new ItbPageModel({
                                updData: updData
                            });
                            updEnt2.updatePagesReplaces(function(err4, updPagesRet){
                                if(err4) {
                                    console.log('mongo.js [chgTmplProc] upd User-Page err:'+err4);
                                    return callback("NG", null);
                                }
                                // 更新成功
                                console.log('mongo.js [chgTmplProc] upd User-Page OK');

                                // 排版生成预览图
                                rpcFunc.typesetDoc(userPages[0].doc_id, function (autoRet) {
                                    return callback(null, relTmplInfo.rel_tmpl_id);// 目标模版id
                                });
                            });
                        });

                    } else {
                        console.log('mongo.js [chgTmplProc] updData NG');
                        return callback("NG", null);
                    }

                } else {
                    console.log('mongo.js [chgTmplProc] tmplPageInfo NULL');
                    return callback("NG", null);
                }
            });
        });
    });
}
//--------------------------------------------------

//--------------------------------------------------
/**
 * 模版取消发布
 * 参数 device
 * 参数 tmplId
 */
function cancelTmpl(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");// 设置跨域访问

    var device = req.body.device || req.query.device;
    var tmplId = Number(req.body.tmplId || req.query.tmplId);

    // return function
    function ret_func(success, msg, data){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    }

    if (typeof tmplId=='undefined' || tmplId==null || tmplId==0) {
        return ret_func(0,"模版id为空");
    }
    
    updOtherRelInfo(tmplId, true, function(err, ret){
        if (err) {
            return ret_func(0,CODE.OPERATION_FAILED);
        }

        return ret_func(1,CODE.OPERATION_SUCCESS);
    });
}
router.get('/cancelTmpl', cancelTmpl);
router.post('/cancelTmpl', cancelTmpl);
//--------------------------------------------------

//--------------------------------------------------
/**
 * 更新所有模版页信息到MongoDB
 */
function refreshAllTmplPageInfo(req, res, next) {
    // return function
    function ret_func(success, msg, data){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    }

    // 获取全部模版
    var entity = new ItbTmplPageModel({
    });
    entity.getAllTmplPagesInfoForSwitch(function(err, allTmplPagesInfo) {
        if (err) {
            console.log('mongo.js [refreshAllTmplPageInfo] get allTmplPagesInfo Err: ' + err);
            return ret_func(0,CODE.OPERATION_FAILED);
        }

        // 返回结果是以模版为单位
        if (allTmplPagesInfo && allTmplPagesInfo.length > 0) {

            db.open(function(err2, db) {
                if (err2) {
                    console.log('mongo.js [refreshAllTmplPageInfo] OpenDB Err: ' + err2);
                    return ret_func(0, CODE.OPERATION_FAILED);
                }
                // DB认证
                db.authenticate(CONFIG.MGDB_USER, CONFIG.MGDB_PASSWORD, function (authErr, authRet) {
                    if (authErr) {
                        console.log('mongo.js [refreshAllTmplPageInfo] DB-Auth Err: ' + authErr);
                        return ret_func(0, CODE.OPERATION_FAILED);
                    }
                    console.log('Open MongoDB');

                    // 循环所有模版
                    var asyncFuncs = [];
                    for(var i in allTmplPagesInfo) {
                        asyncFuncs.push((function(index, tmplData){
                            return function(callback){

                                var collection = db.collection(DB_COL.COL_PAGE_INFO);
                                // 删除旧的页信息
                                collection.deleteMany({"tmpl_id": tmplData.tmpl_id},function(delErr, delRet){
                                    if (delErr) {
                                        console.log('mongo.js [refreshAllTmplPageInfo] del MgDB-PageInfo Err: '+delErr);
                                        return callback(delErr, null);
                                    }

                                    var newData=[];
                                    for(var i in tmplData.pages){
                                        var info=tmplData.pages[i];
                                        newData.push({
                                            tmpl_id: tmplData.tmpl_id,
                                            page_id: info.page_id,
                                            page_index: info.page_index,
                                            base_page_id: info.base_page_id,
                                            rep_hash_tag: info.rep_hash_tag,
                                            replaces: info.replaces,
                                            create_time: new Date().toISOString(),
                                        });
                                    }
                                    // 插入新的页信息
                                    collection.insertMany(newData, function(insErr, insRet){
                                        if (insErr) {
                                            console.log('mongo.js [refreshAllTmplPageInfo] ins MgDB-PageInfo Err: '+insErr);
                                            return callback(insErr, null);
                                        }

                                        return callback(null, newData);
                                    });
                                });
                            }
                        })(i, allTmplPagesInfo[i]));
                    }
                    // 并行执行
                    async.parallelLimit(asyncFuncs, 20, function (err, results) {
                        if (err) {
                            console.log('mongo.js [refreshAllTmplPageInfo] async-AllTmpl Err: '+err);
                            return ret_func(0,CODE.OPERATION_FAILED);
                        }
                        db.close();
                        console.log('Close MongoDB');

                        results = results||[];
                        var pageCnt=0
                        for(var i in results){
                            if(results[i]){
                                pageCnt += results[i].length;
                            }
                        }
                        return ret_func(1,CODE.OPERATION_SUCCESS,
                            {
                                tmpl_cnt:results.length,
                                page_cnt:pageCnt
                            });
                    });
                });
            });

        } else {
            return ret_func(0,'未找到模版');
        }
    });
}
router.get('/refreshAllTmplPageInfo', refreshAllTmplPageInfo);
router.post('/refreshAllTmplPageInfo', refreshAllTmplPageInfo);
//--------------------------------------------------

//--------------------------------------------------
module.exports = router;
